home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / kyocera / dvi.c < prev    next >
C/C++ Source or Header  |  1990-10-01  |  18KB  |  703 lines

  1. /* dvi.c The dvi reader for dvi printers.
  2.  * Copyright 1985 Massachusetts Institute of Technology.
  3.  * Author: cjl@oz
  4.  * Slightly changed by Kees Straatman (mcvax!guvaxin!kees) for Kyocera driver
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <signal.h>
  11. #include "fonts.h"
  12. #include "dev.h"
  13. #include "util.h"
  14. #include "dvi.h"
  15.  
  16. extern char *rindex();
  17. extern char *mktemp();
  18. extern long ftell();
  19.  
  20. #define DVI_STACK_SIZE      512 /* Maximum dvi stack size supported. */
  21. #define NFONTDIR_MAX         16
  22. #define MAXDRIFT              2
  23. #ifndef PXLDIR
  24. #define PXLDIR "/usr/lib/tex/pxlfonts"
  25. #endif
  26.  
  27. /* Runtime parameters specified by user
  28.  */
  29. FILE *out = stdout;
  30. FILE *in;
  31. char *dirvec[NFONTDIR_MAX];
  32. char *acctfile = (char *)0;
  33. int  npages = 0;
  34. int dirveclen;
  35. unsigned long devopts,fontopts;
  36.  
  37. /* Runtime parameters specified by the dvi file & the user
  38.  */
  39. char pre_comment[257];
  40. long numerator,denominator,half_denominator,dvinum,dviden,dvimag;
  41. long globalmag;
  42.  
  43.  
  44. /* Runtime data structures
  45.  */
  46. char stdoutbuf[BUFSIZ];
  47. long h_pix,v_pix,h,v,w,x,y,z,device_dpi,fntspc;
  48. unsigned long fntvec[512],chrvec[512][4];
  49. int stackptr,fntveclen;
  50. long hstack[DVI_STACK_SIZE];
  51. long h_pixstack[DVI_STACK_SIZE];
  52. long vstack[DVI_STACK_SIZE];
  53. long v_pixstack[DVI_STACK_SIZE];
  54. long wstack[DVI_STACK_SIZE];
  55. long xstack[DVI_STACK_SIZE];
  56. long ystack[DVI_STACK_SIZE];
  57. long zstack[DVI_STACK_SIZE];
  58.  
  59. /* Stack manipulation: push and pop
  60.  */
  61.  
  62. push()
  63. {
  64.   if (stackptr >= DVI_STACK_SIZE) croak("dvi stack overflow");
  65.   hstack[stackptr] = h;
  66.   h_pixstack[stackptr] = h_pix;
  67.   vstack[stackptr] = v;
  68.   v_pixstack[stackptr] = v_pix;
  69.   wstack[stackptr] = w;
  70.   xstack[stackptr] = x;
  71.   ystack[stackptr] = y;
  72.   zstack[stackptr] = z;
  73.   stackptr++;
  74. }
  75.  
  76. pop()
  77. {
  78.   if (stackptr <= 0) croak("dvi stack underflow");
  79.   stackptr--;
  80.   h = hstack[stackptr];
  81.   h_pix = h_pixstack[stackptr];
  82.   v = vstack[stackptr];
  83.   v_pix = v_pixstack[stackptr];
  84.   w = wstack[stackptr];
  85.   x = xstack[stackptr];
  86.   y = ystack[stackptr];
  87.   z = zstack[stackptr];
  88. }
  89.  
  90. position()
  91. {
  92.   register int dh = h_pix - (h * numerator + half_denominator) / denominator;
  93.   register int dv = v_pix - (v * numerator + half_denominator) / denominator;
  94.  
  95.   if (dh > MAXDRIFT) h_pix -= MAXDRIFT;
  96.   else if (dh < -MAXDRIFT) h_pix += MAXDRIFT;
  97.   if (dv > MAXDRIFT) v_pix -= MAXDRIFT;
  98.   else if (dv < -MAXDRIFT) v_pix += MAXDRIFT;
  99.   dev_position(h_pix,v_pix);
  100. }
  101.  
  102. /* Drawing: set and setrule
  103.  */
  104. set(ch,movep)
  105.      unsigned long ch;
  106.      int movep;
  107. {
  108.   long texwidth,devwidth;
  109.  
  110.   f_use_char(ch,&texwidth,&devwidth);
  111.   position();
  112.   f_setc(ch,devwidth);
  113.   if (movep) {
  114.     h += texwidth;
  115.     h_pix += devwidth;
  116.   }
  117. }
  118.  
  119. setrule(movep)
  120.      int movep;
  121. {
  122.   long a = sget4(in);
  123.   long b = sget4(in);
  124.   long a_pix,b_pix;
  125.  
  126.   if (a > fntspc || a < -fntspc)
  127.     a_pix = ((v + a) * numerator + half_denominator) / denominator - v_pix;
  128.   else if (a < 0)
  129.     a_pix = - ((-a * numerator + half_denominator) / denominator);
  130.   else
  131.     a_pix = (a * numerator + half_denominator) / denominator;
  132.   if (b > fntspc || b < -fntspc)
  133.     b_pix = ((h + b) * numerator + half_denominator) / denominator - h_pix;
  134.   else if (b < 0)
  135.     b_pix = - ((-b * numerator + half_denominator) / denominator);
  136.   else
  137.     b_pix = (b * numerator + half_denominator) / denominator;
  138.   if (a_pix > 0 && b_pix > 0) {
  139.     position();
  140.     dev_draw_box(a_pix,b_pix);
  141.   }
  142.   if (movep) {
  143.     h += b;
  144.     h_pix += b_pix;
  145.   }
  146. }
  147.  
  148. /* Movement: right and down
  149.  */
  150.  
  151. right(dx)
  152.      long dx;
  153. {
  154.   h += dx;
  155.   if (dx > fntspc || dx < -fntspc * 4)
  156.     h_pix = (h * numerator + half_denominator) / denominator;
  157.   else if (dx < 0)
  158.     h_pix -= (-dx * numerator + half_denominator) / denominator;
  159.   else
  160.     h_pix += (dx * numerator + half_denominator) / denominator;
  161. }
  162.  
  163. down(dy)
  164.      long dy;
  165. {
  166.   v += dy;
  167.   if (dy > fntspc * 5)
  168.     v_pix = (v * numerator + half_denominator) / denominator;
  169.   else if (dy < 0)
  170.     v_pix -= (-dy * numerator + half_denominator) / denominator;
  171.   else
  172.     v_pix += (dy * numerator + half_denominator) / denominator;
  173. }
  174.  
  175.  
  176. /* Special: xxx
  177.  */
  178. xxx(k)
  179.      long k;
  180. {
  181.   position();
  182.   dev_special(k,in);
  183. }
  184.  
  185.  
  186. /* Fonts: fntdef
  187.  */
  188. fntdef(fontnum)
  189.      unsigned long fontnum;
  190. {
  191.   unsigned long tfmchecksum = get4(in);
  192.   long s = sget4(in);
  193.   long d = sget4(in);
  194.   int a = get1(in);
  195.   int l = get1(in);
  196.   int i;
  197.   char area[257];
  198.   char name[257];
  199.   long mag;
  200.  
  201.   for (i = 0; i < a; i++) area[i] = getc(in); area[a] = 0;
  202.   for (i = 0; i < l; i++) name[i] = getc(in); name[l] = 0;
  203.   mag = (long) (((double) s) * ((double) globalmag) / ((double) d));
  204.   debug("fntdef: num= %d area=\"%s\" name=\"%s\" mag=%d s=%d d=%d\n",
  205.     fontnum,area,name,mag,s,d);
  206.   f_define_font(fontnum,0,area,name,mag,s,tfmchecksum);
  207. }
  208.  
  209. /* Fonts: fntdef
  210.  */
  211. nullfntdef(fontnum)
  212.      unsigned long fontnum;
  213. {
  214.   register int a,l,i;
  215.  
  216.   (void) getc(in); (void) getc(in); (void) getc(in); (void) getc(in);
  217.   (void) getc(in); (void) getc(in); (void) getc(in); (void) getc(in);
  218.   (void) getc(in); (void) getc(in); (void) getc(in); (void) getc(in);
  219.   a = getc(in);
  220.   l = getc(in);
  221.   for (i = 0; i < a; i++) (void) getc(in);
  222.   for (i = 0; i < l; i++) (void) getc(in);
  223. }
  224.  
  225. /* Record this font number on fntvec
  226.  * We'll later pass fntvec to the fonts module
  227.  */
  228. int fntmark(fnt)
  229.      unsigned long fnt;
  230. {
  231.   register int i;
  232.  
  233.   for (i = 0; i < fntveclen; i++) if (fntvec[i] == fnt) return(i);
  234.   if (fntveclen >= sizeof(fntvec)) croak("too many fonts");
  235.   chrvec[fntveclen][0] = 0;
  236.   chrvec[fntveclen][1] = 0;
  237.   chrvec[fntveclen][2] = 0;
  238.   chrvec[fntveclen][3] = 0;
  239.   fntvec[fntveclen] = fnt;
  240.   return(fntveclen++);
  241. }
  242.  
  243. chrmark(ch,i)
  244.      unsigned long ch;
  245.      int i;
  246. {
  247.   chrvec[i][ch/32] |= (1 << (ch % 32));
  248. }
  249.  
  250. /* End of page processing: eop
  251.  */
  252. eop()
  253. {
  254.   dev_eop();
  255. }
  256.  
  257. noprint_page(c,p)
  258.      long c[10];
  259.      long p;
  260. {
  261.   int f;
  262.   register int ch;
  263.  
  264.   (void) c; (void) p;
  265.   fntveclen = 0;
  266.   for (;;) {
  267.     if (ferror(in)) croak("noprint_page dvi input");
  268.     switch (ch = getc(in)) {
  269.     case SETRULE:
  270.     case PUTRULE:
  271.       (void) getc(in);
  272.       (void) getc(in);
  273.       (void) getc(in);
  274.       (void) getc(in);
  275.  
  276.     case RIGHT4:
  277.     case W4:
  278.     case DOWN4:
  279.     case X4:
  280.     case Y4:
  281.     case Z4:
  282.       (void) getc(in);
  283.  
  284.     case RIGHT3:
  285.     case W3:
  286.     case X3:
  287.     case DOWN3:
  288.     case Y3:
  289.     case Z3:
  290.       (void) getc(in);
  291.  
  292.     case RIGHT2:
  293.     case W2:
  294.     case X2:
  295.     case DOWN2:
  296.     case Y2:
  297.     case Z2:
  298.       (void) getc(in);
  299.  
  300.     case RIGHT1:
  301.     case W1:
  302.     case X1:
  303.     case DOWN1:
  304.     case Y1:
  305.     case Z1:
  306.       (void) getc(in);
  307.  
  308.     case NOP:
  309.     case PUSH:
  310.     case POP:
  311.     case W0:
  312.     case X0:
  313.     case Y0:
  314.     case Z0:
  315.       break;
  316.  
  317.     case EOP:
  318.       return;
  319.  
  320.  
  321.     case SET1:
  322.     case PUT1:          chrmark(get1(in),f);    break;
  323.     case SET2:
  324.     case PUT2:          chrmark(get2(in),f);    break;
  325.     case SET3:
  326.     case PUT3:          chrmark(get3(in),f);    break;
  327.     case SET4:
  328.     case PUT4:          chrmark(get4(in),f);    break;
  329.     case FNT1:          f = fntmark(get1(in));  break;
  330.     case FNT2:          f = fntmark(get2(in));  break;
  331.     case FNT3:          f = fntmark(get3(in));  break;
  332.     case FNT4:          f = fntmark(get4(in));  break;
  333.     case FNTDEF1:       nullfntdef(get1(in));   break;
  334.     case FNTDEF2:       nullfntdef(get2(in));   break;
  335.     case FNTDEF3:       nullfntdef(get3(in));   break;
  336.     case FNTDEF4:       nullfntdef(get4(in));   break;
  337.     case XXX1:          swallow(get1(in),in);   break;
  338.     case XXX2:          swallow(get2(in),in);   break;
  339.     case XXX3:          swallow(get3(in),in);   break;
  340.     case XXX4:          swallow(get4(in),in);   break;
  341.  
  342.     case EOF:
  343.       croak("noprint_page EOF between BOP and EOP");
  344.       break;
  345.  
  346.     default:
  347.       if (ch >= SETCHAR0 && ch <= SETCHAR127)
  348.     chrmark((unsigned long) (ch - SETCHAR0),f);
  349.       else if (ch >= FNTNUM0 && ch <= FNTNUM63)
  350.     f = fntmark((unsigned long) (ch - FNTNUM0));
  351.       else croak("noprint_page dvi command %d between BOP and EOP",ch);
  352.       break;
  353.     }
  354.   }
  355. }
  356.  
  357. print_page(c,p)
  358.      long c[10];
  359.      long p;
  360. {
  361.   long ch;
  362.  
  363.   (void) p;
  364.   stackptr = 0;
  365.   h = v = w = x = y = z = h_pix = v_pix = 0;
  366.   position();
  367.   for (;;) {
  368.     if (ferror(in)) croak("print_page dvi input");
  369.     switch (ch = getc(in)) {
  370.     case EOF:
  371.       croak("print_page EOF between BOP and EOP");
  372.       break;
  373.  
  374.     case SET1:          set(get1(in),1);        break;
  375.     case SET2:          set(get2(in),1);        break;
  376.     case SET3:          set(get3(in),1);        break;
  377.     case SET4:          set(get4(in),1);        break;
  378.     case SETRULE:       setrule(1);             break;
  379.     case PUT1:          set(get1(in),0);        break;
  380.     case PUT2:          set(get2(in),0);        break;
  381.     case PUT3:          set(get3(in),0);        break;
  382.     case PUT4:          set(get4(in),0);        break;
  383.     case PUTRULE:       setrule(0);             break;
  384.     case NOP:                                   break;
  385.     case EOP:           eop();                  return;
  386.     case PUSH:          push();                 break;
  387.     case POP:           pop();                  break;
  388.     case RIGHT1:        right(sget1(in));       break;
  389.     case RIGHT2:        right(sget2(in));       break;
  390.     case RIGHT3:        right(sget3(in));       break;
  391.     case RIGHT4:        right(sget4(in));       break;
  392.     case W0:            right(w);               break;
  393.     case W1:            right(w = sget1(in));   break;
  394.     case W2:            right(w = sget2(in));   break;
  395.     case W3:            right(w = sget3(in));   break;
  396.     case W4:            right(w = sget4(in));   break;
  397.     case X0:            right(x);               break;
  398.     case X1:            right(x = sget1(in));   break;
  399.     case X2:            right(x = sget2(in));   break;
  400.     case X3:            right(x = sget3(in));   break;
  401.     case X4:            right(x = sget4(in));   break;
  402.     case DOWN1:         down(sget1(in));        break;
  403.     case DOWN2:         down(sget2(in));        break;
  404.     case DOWN3:         down(sget3(in));        break;
  405.     case DOWN4:         down(sget4(in));        break;
  406.     case Y0:            down(y);                break;
  407.     case Y1:            down(y = sget1(in));    break;
  408.     case Y2:            down(y = sget2(in));    break;
  409.     case Y3:            down(y = sget3(in));    break;
  410.     case Y4:            down(y = sget4(in));    break;
  411.     case Z0:            down(z);                break;
  412.     case Z1:            down(z = sget1(in));    break;
  413.     case Z2:            down(z = sget2(in));    break;
  414.     case Z3:            down(z = sget3(in));    break;
  415.     case Z4:            down(z = sget4(in));    break;
  416.     case FNT1:          f_use_font(get1(in),&fntspc);   break;
  417.     case FNT2:          f_use_font(get2(in),&fntspc);   break;
  418.     case FNT3:          f_use_font(get3(in),&fntspc);   break;
  419.     case FNT4:          f_use_font(get4(in),&fntspc);   break;
  420.     case FNTDEF1:       nullfntdef(get1(in));   break;
  421.     case FNTDEF2:       nullfntdef(get2(in));   break;
  422.     case FNTDEF3:       nullfntdef(get3(in));   break;
  423.     case FNTDEF4:       nullfntdef(get4(in));   break;
  424.     case XXX1:          xxx(get1(in));          break;
  425.     case XXX2:          xxx(get2(in));          break;
  426.     case XXX3:          xxx(get3(in));          break;
  427.     case XXX4:          xxx(get4(in));          break;
  428.  
  429.     default:
  430.       if (ch >= SETCHAR0 && ch <= SETCHAR127)
  431.     set((unsigned long) (ch - SETCHAR0),1);
  432.       else if (ch >= FNTNUM0 && ch <= FNTNUM63)
  433.     f_use_font((unsigned long) (ch - FNTNUM0),&fntspc);
  434.       else croak("print_page dvi command %d between BOP and EOP",ch);
  435.       break;
  436.     }
  437.   }
  438. }
  439.  
  440. /* Preamble processing.
  441.  */
  442. computescale()
  443. {
  444.   double dd;
  445.  
  446.   /* Compute scale factors for this file. */
  447.   globalmag = dvimag;
  448.  
  449.   /* This is real hokey, but will probably work for TEX82. */
  450.   if (dvinum != 25400000 || dviden != 473628672) {
  451.     fprintf(stderr,"DVI file numerator and denominator weren't exactly ");
  452.     fprintf(stderr,"what was expected.\nScaling may be wrong.\n");
  453.   }
  454.   numerator = ((long) (((double) dvinum)
  455.                / ((double) 254000)
  456.                / ((double) 10)));
  457.   denominator = ((long) (((double) dviden)
  458.              / ((double) globalmag)
  459.              * ((double) 1000)
  460.              / ((double) device_dpi)
  461.              / ((double) 10)));
  462.   half_denominator = denominator / 2;
  463.   debug("Computescale: globalmag=%d numerator=%d denominator=%d\n",
  464.     globalmag,numerator,denominator);
  465.  
  466. }
  467.  
  468.  
  469. preamble()
  470. {
  471.   int i = getc(in);
  472.   int k;
  473.  
  474.   dvinum = get4(in);
  475.   dviden = get4(in);
  476.   dvimag = get4(in);
  477.   k = get1(in);
  478.   if (i != 2) croak("id_byte=%d, probably not a dvi file",i);
  479.   for (i = 0; i < k; i++) pre_comment[i] = getc(in);
  480.   pre_comment[k] = '\0';
  481.   computescale();
  482.   debug("Preamble: dvinum=%d dviden=%d dvimag=%d\n",
  483.     dvinum,dviden,dvimag);
  484.   debug("          comment: \"%s\"\n",pre_comment);
  485. }
  486.  
  487. /* Beginning of page processing
  488.  */
  489. bop()
  490. {
  491.   int i;
  492.   long c[10];
  493.   long p,fpos;
  494.  
  495.   for (i = 0; i < 10; i++) c[i] = sget4(in);
  496.   p = sget4(in);
  497.   debug("first pass of page %d\n",c[0]);
  498.   fpos = ftell(in);           /* Remember where we are */
  499.   noprint_page(c,p);          /* First pass noprint to get fntvec */
  500.   /* Tell font module about the fonts */
  501.   f_newpage(fntvec,chrvec,fntveclen);
  502.   debug("second pass of page %d\n",c[0]);
  503.   fseek(in,fpos,0);           /* Back up */
  504.   print_page(c,p);            /* And finally do the page */
  505.   debug("done with page %d\n",c[0]);
  506.   npages++;
  507. }
  508.  
  509. file_term()
  510. {
  511.   f_term();
  512.   close_ef();
  513.   dev_term();
  514. }
  515.  
  516. /* Postamble processing.
  517.  */
  518.  
  519. find_postamble()
  520. {
  521.   int ch;
  522.   long i = -4;
  523.   long q;
  524.  
  525.   do (void) fseek(in,i--,2); while ((ch = getc(in)) == TRAILER);
  526.   if (ch != 2) croak("postamble id_byte=%d, probably not a dvi file",ch);
  527.   (void) fseek(in,i-4,2);
  528.   if ((ch = getc(in)) != POSTPOST) croak("no POSTPOST where expected");
  529.   q = sget4(in);
  530.   (void) fseek(in,q,0);
  531.   if ((ch = getc(in)) != POST) croak("no POST where expected");
  532. }
  533.  
  534.  
  535. postamble()
  536. {
  537.   int ch;
  538.   long p = sget4(in);
  539.   unsigned long l,u,maxstackdepth,npages;
  540.  
  541.   dvinum = get4(in);
  542.   dviden = get4(in);
  543.   dvimag = get4(in);
  544.   computescale();
  545.   l = get4(in);
  546.   u = get4(in);
  547.   maxstackdepth = get2(in);
  548.   npages = get2(in);
  549.   debug("Postamble: dvinum=%d dviden=%d dvimag=%d maxstackdepth=%d\n",
  550.     dvinum,dviden,dvimag,maxstackdepth);
  551.   debug("           npages=%d\n",npages);
  552.   if (maxstackdepth > DVI_STACK_SIZE)
  553.     croak("dvi file has too much stack depth");
  554.   f_init(out,pgmnam,dirvec,dirveclen,numerator
  555.      ,denominator,globalmag,fontopts);
  556.   signal(SIGINT, file_term);
  557.   for (;;) {
  558.     if (ferror(in)) croak("postamble input");
  559.     switch (ch = getc(in)) {
  560.     case EOF:
  561.       croak("EOF found before POSTPOST");
  562.       break;
  563.  
  564.     case FNTDEF1:       fntdef(get1(in));       break;
  565.     case FNTDEF2:       fntdef(get2(in));       break;
  566.     case FNTDEF3:       fntdef(get3(in));       break;
  567.     case FNTDEF4:       fntdef(get4(in));       break;
  568.     case NOP:                                   break;
  569.     case POSTPOST:                              return;
  570.  
  571.     default:
  572.       croak("dvi command %d in postamble",ch);
  573.       break;
  574.     }
  575.   }
  576. }
  577.  
  578. /* Process a dvi file
  579.  */
  580. file_init()
  581. {
  582.   int ch;
  583.  
  584.   if ((ch = getc(in)) != PRE)
  585.     croak("first char %d not PRE, probably not a dvi file",ch);
  586.   find_postamble();
  587.   dev_init(out,devopts,&device_dpi);
  588.   open_ef();
  589.   postamble();
  590.   (void) fseek(in,1L,0);
  591.   preamble();
  592. }
  593.  
  594. dvi_file()
  595. {
  596.   int ch;
  597.  
  598.   if (!dirveclen) dirvec[dirveclen++] = PXLDIR;
  599.   file_init();
  600.   for (;;) {
  601.     if (ferror(in)) croak("dvi_file input");
  602.     switch (ch = getc(in)) {
  603.     case EOF:
  604.       croak("EOF found between pages");
  605.       break;
  606.  
  607.     case BOP:           bop();                  break;
  608.     case POST:          file_term();            return;
  609.     case FNTDEF1:       fntdef(get1(in));       break;
  610.     case FNTDEF2:       fntdef(get2(in));       break;
  611.     case FNTDEF3:       fntdef(get3(in));       break;
  612.     case FNTDEF4:       fntdef(get4(in));       break;
  613.     case NOP:                                   break;
  614.  
  615.     default:
  616.       croak("dvi command %d between pages",ch);
  617.       break;
  618.     }
  619.   }
  620. }
  621.  
  622. process_stdin()
  623. {
  624.   int ch;
  625.   FILE *tf;
  626.   char tfn[257];
  627.   struct stat st;
  628.  
  629.   if (fstat(fileno(stdin),&st) < 0) croak("can't stat stdin");
  630.   if ((st.st_mode & S_IFMT) == S_IFREG) {
  631.     in = stdin; infname = "stdin";
  632.     dvi_file();
  633.     in = NULL; infname = NULL;
  634.   } else {
  635.     /* Copy the dvi data to a temp file, since we have to do disk seeks. */
  636.     (void) sprintf(tfn,"/usr/tmp/%s.XXXXXX",pgmnam);
  637.     if (!(tf = fopen(mktemp(tfn),"w"))) croak("couldn't open %s",tfn);
  638.     unlink(tfn);
  639.     while (!ferror(stdin) && (ch = getchar()) != EOF) putc(ch,tf);
  640.     if (ferror(stdin)) croak("error on stdin");
  641.     (void) fseek(tf,0L,0);
  642.     infname = tfn; in = tf;
  643.     dvi_file();
  644.     in = NULL; infname = NULL;
  645.     (void) fclose(tf);
  646.   }
  647. }
  648.  
  649. account()
  650. {
  651.   FILE *acctf;
  652.  
  653.   if (user && acctfile && access(acctfile, 02) >= 0 &&
  654.       ((acctf = fopen(acctfile, "a")) != NULL)) {
  655.     fprintf(acctf, "%-5d\t%s:%s\n", npages, host, user);
  656.     fclose(acctf);
  657.   }
  658. }
  659.  
  660. main(argc,argv)
  661.      int argc;
  662.      char *argv[];
  663. {
  664.   FILE *f;
  665.   int nfiles = 0;
  666.   int i;
  667.  
  668.   setbuf(stdout,stdoutbuf);
  669.   pgmnam = argv[0];
  670.   fontopts = 0;
  671.   devopts = 0;
  672.  
  673.  
  674.   for (i = 1; i < argc; i++)
  675.     if (argv[i][0] == '-') switch(argv[i][1]) {
  676.  
  677.     case 'd':
  678.       debugging++;
  679.       break;
  680.  
  681.     case 'h':
  682.       host = argv[++i];
  683.       break;
  684.  
  685.     case 'n':
  686.       user = argv[++i];
  687.       break;
  688.  
  689.     case 'x':
  690.     case 'y':
  691.       break;
  692.  
  693.     default:
  694.       croak("bad switch: %s",argv[i]);
  695.       break;
  696.   } else
  697.     acctfile  = argv[i];
  698.  
  699.   process_stdin();
  700.   account();
  701.   exit(0);
  702. }
  703.